package com.wzcl.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.wzcl.app.dao.model.Commodity;
import com.wzcl.app.dao.model.Course;
import com.wzcl.app.dao.model.CourseMaterial;
import com.wzcl.app.dao.model.Material;
import com.wzcl.app.dao.repository.CourseMaterialRepository;
import com.wzcl.app.model.common.BusinessException;
import com.wzcl.app.model.common.CodeMsg;
import com.wzcl.app.model.common.MyPage;
import com.wzcl.app.model.dto.CourseMaterialDto;
import com.wzcl.app.service.CourseMaterialService;
import com.wzcl.app.service.CourseService;
import com.wzcl.app.service.MaterialService;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Log4j2
@Service
public class CourseMaterialServiceImpl implements CourseMaterialService {

    @Autowired
    private CourseMaterialRepository repository;

    @Autowired
    private CourseService courseService;

    @Autowired
    private MaterialService materialService;

    @Override
    public CourseMaterial addCourseMaterial(CourseMaterialDto courseMaterialDto) {
        CourseMaterial courseMaterial = new CourseMaterial();
        BeanUtils.copyProperties(courseMaterialDto, courseMaterial, "id");
        //校验课程
        Course course = courseService.getAndCheckById(courseMaterial.getCourseId());
        //校验物品
        Material material = materialService.getAndCheckById(courseMaterial.getMaterialId());
        //补充(默认物品名为教材名，物品描述为教材描述)
        if (StringUtils.isBlank(courseMaterial.getName())) {
            courseMaterial.setName(material.getName());
        }
        if (StringUtils.isBlank(courseMaterial.getDescription())) {
            courseMaterial.setDescription(material.getDescription());
        }
        //修改课程图书状态
        if (course.getHaveBook()) {
            List<CourseMaterial> list = getCourseMaterialListByCourseId(course.getId());
            for (CourseMaterial courseMaterial1 : list) {
                if (courseMaterial1.getMaterialId().equals(material.getId())) {
                    log.info("CourseMaterial {}：is existed. pass request return this", JSON.toJSONString(material));
                    return courseMaterial1;
                }
            }
        } else {
            course.setHaveBook(true);
            courseService.saveCourse(course);
            log.info("course {}：set property 'HaveBook' into true", JSON.toJSONString(course));
        }
        return repository.save(courseMaterial);
    }

    @Override
    public CourseMaterial delCourseMaterialById(Integer id) {
        //校验获取
        CourseMaterial courseMaterial = getAndCheckById(id);
        log.info("CourseMaterial:{} Physical deletion", JSON.toJSONString(courseMaterial));
        repository.delete(courseMaterial);
        List<CourseMaterial> list = getCourseMaterialListByCourseId(courseMaterial.getCourseId());
        if (list == null || list.size() == 0) {
            Course course = courseService.getCourseById(courseMaterial.getCourseId());
            if (course != null) {
                course.setHaveBook(false);
                courseService.saveCourse(course);
                log.info("course {}：set property 'HaveBook' into false", JSON.toJSONString(course));
            }
        }
        return courseMaterial;
    }

    @Override
    public CourseMaterial updateCourseMaterial(CourseMaterialDto courseMaterialDto) {
        //校验获取
        CourseMaterial courseMaterial = getAndCheckById(courseMaterialDto);
        //修改
        if (!StringUtils.isBlank(courseMaterialDto.getName())) {
            courseMaterial.setName(courseMaterialDto.getName());
        }
        if (!StringUtils.isBlank(courseMaterialDto.getDescription())) {
            courseMaterial.setDescription(courseMaterialDto.getDescription());
        }
        return repository.save(courseMaterial);
    }

    @Override
    public CourseMaterial getCourseMaterialById(Integer id) {
        return repository.findById(id).orElse(null);
    }

    @Override
    public CourseMaterial getAndCheckById(Integer id) {
        if (id == null) {
            throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL, "缺少课程教材Id");
        }
        CourseMaterial courseMaterial = getCourseMaterialById(id);
        if (courseMaterial == null) {
            throw new BusinessException(CodeMsg.COURSE_MATERIAL_NOT_EXIST);
        }
        return courseMaterial;
    }

    @Override
    public List<CourseMaterial> getCourseMaterialList(CourseMaterialDto courseMaterialDto) {
        return repository.findAll(getSpecification(courseMaterialDto), courseMaterialDto.getSort());
    }

    /**
     * 获取课程所有的教材
     *
     * @param id
     * @return
     */
    @Override
    public List<CourseMaterial> getCourseMaterialListByCourseId(Integer id) {
        return repository.findAllByCourseId(id);
    }

    @Override
    public MyPage<CourseMaterial> getCourseMaterialPage(CourseMaterialDto courseMaterialDto) {
        Page<CourseMaterial> all = repository.findAll(getSpecification(courseMaterialDto), courseMaterialDto.getPageable());
        ArrayList<CourseMaterial> list = new ArrayList<>(all.getContent());
        Collections.reverse(list);
        MyPage<CourseMaterial> myPage = new MyPage<>();
        myPage.setContent(list);
        myPage.setTotalElements(all.getTotalElements());
        return myPage;
    }

    private Specification<CourseMaterial> getSpecification(CourseMaterialDto courseMaterialDto) {
        return new Specification<CourseMaterial>() {
            @Override
            public Predicate toPredicate(Root<CourseMaterial> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<Predicate>();
                if (StringUtils.isNotBlank(courseMaterialDto.getName())) {
                    predicates.add(criteriaBuilder.like(root.get("name"), "%" + courseMaterialDto.getName() + "%"));
                }
                if (courseMaterialDto.getCourseId() != null) {
                    predicates.add(criteriaBuilder.equal(root.get("courseId"), courseMaterialDto.getCourseId()));
                }
                if (courseMaterialDto.getMaterialId() != null) {
                    predicates.add(criteriaBuilder.equal(root.get("materialId"), courseMaterialDto.getMaterialId()));
                }
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
    }


}
